#pragma once

#include "application/pathfinding/pathfinding_graph.h"
#include <QVector>
#include <QString>
#include <memory>
#include <string>
#include <vector>
#include <functional>

namespace kernel {
class ILogger;
}

namespace application {
namespace pathfinding {

struct AgentRequest {
    int agvNumber{0};
    QString startId;
    QString goalId;
    qint64 requestOrder{0};  // lower = earlier request priority
};

struct AgentPlan {
    int agvNumber{0};
    QVector<QString> route; // time-expanded sequence of node ids
    QVector<int> times;     // time index per route entry
};

class MultiAgentSolver {
public:
    MultiAgentSolver() = default;
    ~MultiAgentSolver() = default;

    void setLogger(std::shared_ptr<kernel::ILogger> logger);
    void setVerboseLogging(bool enabled);
    bool verboseLogging() const { return verboseLogging_; }
    // Optional: provide a cancel checker that returns true when solver should abort early
    void setCancelCallback(std::function<bool()> cancelCallback) { cancelCallback_ = std::move(cancelCallback); }

    void buildFromGraph(PathfindingGraphPtr graph);

    // Solve MAPF for given agent requests. Returns true on success and fills plans.
    bool solve(const std::vector<AgentRequest>& requests,
               std::vector<AgentPlan>& plans,
               double suboptimality = 1.5) const;

private:
    struct Impl;
    std::shared_ptr<Impl> impl_;
    std::shared_ptr<kernel::ILogger> logger_;
    bool verboseLogging_{false};
    std::function<bool()> cancelCallback_;

    void logDebug(const QString& message) const;
    void logInfo(const QString& message) const;
    void logWarning(const QString& message) const;
    void logError(const QString& message) const;
    void logVerbose(const QString& message) const;
};

} // namespace pathfinding
} // namespace application
